import { Controller } from "../Controller.js";
import { ContextMenu, AnnotationsPlugin, math } from "@xeokit/xeokit-sdk";
import { post, get } from "../server/Http.js"

/** @private */
export class AnnotationsTool extends Controller {

    constructor(parent, cfg) {

        super(parent);
        console.log(this)
        this._projectId = cfg.projectId;
        if (!cfg.buttonElement) {
            throw "Missing config: buttonElement";
        }

        const buttonElement = cfg.buttonElement;

        this._contextMenu = new ContextMenu({
            items: [
                [
                    {
                        getTitle: (context) => {
                            return context.measurement.axisVisible ? "Hide Measurement Axis" : "Show Measurement Axis";
                        },
                        doAction: function (context) {
                            context.measurement.axisVisible = !context.measurement.axisVisible;
                        }
                    },
                    {
                        getTitle: (context) => {
                            return context.measurement.labelsVisible ? "Hide Measurement Labels" : "Show Measurement Labels";
                        },
                        doAction: function (context) {
                            context.measurement.labelsVisible = !context.measurement.labelsVisible;
                        }
                    }
                ], [
                    {
                        title: "Delete Measurement",
                        doAction: function (context) {
                            context.measurement.destroy();
                        }
                    }
                ]
            ]
        });
        this.on("enabled", (enabled) => {
            if (!enabled) {
                buttonElement.classList.add("disabled");
            } else {
                buttonElement.classList.remove("disabled");
            }
        });
        let numAnnotations = 0;
        this.on("active", (active) => {
            var i = 1;
            if (active) {
                buttonElement.classList.add("active");
                //拾取点，生成标记
                this._onPick = this.viewer.scene.input.on("mouseclicked", (coords) => {


                    // post("/mark/insert", entityCenter).then(console.log).catch(console.error);
                    // const metaObject = this.viewer.metaScene.metaObjects[entity.id];

                    const pickResult = this.viewer.scene.pick({
                        canvasPos: coords,
                        pickSurface: true  // <<------ This causes picking to find the intersection point on the entity
                    });
                    if (pickResult) {
                        const annotation = this._annotationsPlugin.createAnnotation({
                            id: "myAnnotation" + i,
                            pickResult: pickResult, // <<------- initializes worldPos and entity from PickResult
                            occludable: true,       // Optional, default is true
                            markerShown: true,      // Optional, default is true
                            labelShown: true,       // Optional, default is true
                            values: {               // HTML template values
                                glyph: "A" + i,
                                title: "My annotation " + i,
                                description: "My description " + i
                            },
                        });
                        post("/mark/insert", {
                            positionX: annotation.worldPos[0],
                            positionY: annotation.worldPos[1],
                            positionZ: annotation.worldPos[2],
                            viewPos: JSON.stringify({ eye: this.viewer.camera.eye, look: this.viewer.camera.look, up: this.viewer.camera.up }),
                            projectUuid: cfg.projectId,
                            entityId: annotation.entity.id,
                        }).then((res) => {
                            if (res.code === 0) {
                                // console.log(annotation.id)
                                // this._annotationsPlugin.destroyAnnotation(annotation.id)
                                // this.createAnnotation(res.data)
                                this.bimViewer._annotationsInspector.refreshData();
                            }
                        }).catch(console.error);
                        i++;
                    }

                });
            } else {
                buttonElement.classList.remove("active");
                // this._distanceMeasurementsMouseControl.deactivate();
                if (this._onPick !== undefined) {
                    this.viewer.scene.input.off(this._onPick);
                    this._onPick = undefined;
                }
            }
            // if (active) {
            //     buttonElement.classList.add("active");
            //     //拾取点，生成标记
            //     this._onPick = this.viewer.cameraControl.on("picked", (pickResult) => {

            //         const entity = pickResult.entity;
            //         const aabb = entity.aabb;
            //         const entityCenter = math.getAABB3Center(aabb);
            //         console.log(entityCenter);
            //         post("/mark/insert", entityCenter).then(console.log).catch(console.error);
            //         const metaObject = this.viewer.metaScene.metaObjects[entity.id];

            //         this._annotationsPlugin.createAnnotation({
            //             id: "myAnnotation1",
            //             entity: entity,
            //             worldPos: entityCenter,
            //             occludable: false,
            //             markerShown: true,
            //             labelShown: true,

            //             values: {
            //                 glyph: "" + numAnnotations++,
            //                 title: entity.id,
            //                 description: metaObject ? ("This object is a: " + metaObject.type) : "No description available",
            //                 markerBGColor: "green"
            //             }
            //         });
            //     });
            // } else {
            //     buttonElement.classList.remove("active");
            //     // this._distanceMeasurementsMouseControl.deactivate();
            //     if (this._onPick !== undefined) {
            //         this.viewer.cameraControl.off(this._onPick);
            //         this._onPick = undefined;
            //     }
            // }
        });
        buttonElement.addEventListener("click", (event) => {
            if (this.getEnabled()) {
                const active = this.getActive();
                this.setActive(!active);
            }
            event.preventDefault();
        });
        this.bimViewer.on("reset", () => {
            this.setActive(false);
            // this.clear();
        });
        this._contextMenu.on("hidden", () => {
            if (this._contextMenu.context.measurement) {
                this._contextMenu.context.measurement.setHighlighted(false);
            }
        });


        this._annotationsPlugin = new AnnotationsPlugin(this.viewer, {

            markerHTML: "<div class='annotation-marker' style='background-color: {{markerBGColor}};'>{{glyph}}</div>",
            labelHTML: "<div class='annotation-label' style='background-color: {{labelBGColor}};'><div class='annotation-title'>{{title}}</div><div class='annotation-desc'>{{description}}</div></div>",

            values: {
                markerBGColor: "red",
                glyph: "X",
                title: "Untitled",
                description: "No description"
            },

            // Amount to offset each Annotation from its Entity surface (0.3 is the default value).
            // This is useful when the Annotation is occludable, which is when it is hidden when occluded
            // by other objects. When occludable, there is potential for the Annotation#worldPos to become
            // visually embedded within the surface of its Entity when viewed from a distance. This happens
            // as a result of limited GPU accuracy GPU accuracy, especially when the near and far view-space clipping planes,
            // specified by Perspective#near and Perspective#far, or Ortho#near and Perspective#far, are far away from each other.
            //
            // Offsetting the Annotation may ensure that it does become visually embedded within its Entity. We may also
            // prevent this by keeping the distance between the view-space clipping planes to a minimum. In general, a good
            // default value for Perspective#far and Ortho#far is around ````2.000````.

            surfaceOffset: 0.1
        });
        this.prevAnnotationClicked = null;
        this._annotationsPlugin.on("markerClicked", (annotation) => {
            // annotation.labelShown = !annotation.labelShown;
            if (this.prevAnnotationClicked && this.prevAnnotationClicked.id === annotation.id) {
                this.prevAnnotationClicked.setLabelShown(false);
                this.prevAnnotationClicked = null;
                return;
            }
            if (this.prevAnnotationClicked) {
                this.prevAnnotationClicked.setLabelShown(false);
            }
            annotation.setLabelShown(true);
            this.viewer.cameraFlight.flyTo(annotation);
            this.prevAnnotationClicked = annotation;
        });
        var i = 1;


        let editedAnnotation = null;

        this._annotationsPlugin.on("contextmenu", annotation => {
            // Initiate annotation's position change
            editedAnnotation = annotation;
            editedAnnotation.setField("markerBGColor", "pink");
        });
    }

    init() {

        // get("/mark/list", { projectUuid: this._projectId }).then((res) => {
        //     if (res.code === 0) {
        //         this.createAnnotations(res.data)
        //     }
        // }).catch();

    }
    createAnnotations(data) {
        this._annotationsPlugin.clear()
        data.forEach(parojectMark => {
            this.createAnnotation(parojectMark);
        });
    }
    createAnnotation(parojectMark) {
        const viewPos = JSON.parse(parojectMark.viewPos)
        this._annotationsPlugin.createAnnotation({
            id: parojectMark.uuid,
            entity: this.viewer.scene.objects[parojectMark.entityId],
            worldPos: [parojectMark.positionX, parojectMark.positionY, parojectMark.positionZ],
            occludable: true,
            markerShown: true,
            labelShown: false,
            eye: [viewPos.eye[0], viewPos.eye[1], viewPos.eye[2]],
            up: [viewPos.up[0], viewPos.up[1], viewPos.up[2]],
            look: [viewPos.look[0], viewPos.look[1], viewPos.look[2]],
            values: {
                glyph: parojectMark.number,
                title: parojectMark.title,
                description: parojectMark.content,
                markerBGColor: parojectMark.title === "一般" ? "green" : "red"
            }
        });
    }
    remove(id) {
        this._annotationsPlugin.destroyAnnotation(id);
    }
    flyTo(id) {
        if (this.prevAnnotationClicked && this.prevAnnotationClicked.id === id) {
            this.prevAnnotationClicked.setLabelShown(false);
            this.prevAnnotationClicked = null;
            return;
        }
        if (this.prevAnnotationClicked) {
            this.prevAnnotationClicked.setLabelShown(false);
        }
        var annotation = this._annotationsPlugin.annotations[id];
        annotation.setLabelShown(true);
        this.viewer.cameraFlight.flyTo(annotation);
        this.prevAnnotationClicked = annotation;
    }
    getNumMeasurements() {
        return Object.keys(this._annotationsPlugin.measurements).length;
    }

    setMeasurementsAxisVisible(axisVisible) {
        this._annotationsPlugin.setAxisVisible(axisVisible);
    }

    getMeasurementsAxisVisible() {
        return this._annotationsPlugin.getAxisVisible();
    }

    setSnappingEnabled(snappingEnabled) {
        return this._distanceMeasurementsMouseControl.snapping = snappingEnabled;
    }

    getSnappingEnabled() {
        return this._distanceMeasurementsMouseControl.snapping;
    }

    clear() {
        // this._annotationsPlugin.clear();
    }

    destroy() {
        this._annotationsPlugin.destroy();
        this._distanceMeasurementsMouseControl.destroy();
        this._contextMenu.destroy();
        super.destroy();
    }
}